﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using NHibernate;
using NHibernate.Linq;
using Spring.Data.NHibernate.Generic.Support;
using System.Data;
using GONES.Model;
using GONES.IDAL;

namespace GONES.DAL
{
    public class Repository<T> : HibernateDaoSupport, IRepository<T> where T : EntityBase
    {
        #region IRepository<T> Members

        public virtual T Get(object id)
        {
            if (id == null) throw new ArgumentNullException("id");
            return HibernateTemplate.Get<T>(id);
        }


        public virtual object Save(T model)
        {
            if (model == null) throw new ArgumentNullException("model");
            return HibernateTemplate.Save(model);
        }

        public virtual void Update(T model)
        {
            if (model == null) throw new ArgumentNullException("model");
            HibernateTemplate.Update(model);
        }

        public virtual void SaveOrUpdate(T model)
        {
            if (model == null) throw new ArgumentNullException("model");
            HibernateTemplate.SaveOrUpdate(model);
        }

        public virtual void Delete(T model)
        {
            if (model == null) throw new ArgumentNullException("model");
            HibernateTemplate.Delete(model);
        }

        /// <summary>
        /// 取记录列表
        /// </summary>
        /// <returns></returns>
        public virtual IQueryable<T> GetList()
        {
            return Session.Linq<T>();
        }

        /// <summary>
        /// 跟据Hql返回长整形
        /// </summary>
        /// <param name="hql"></param>
        /// <returns></returns>
        public long ExecHqlResultLong(string hql)
        {
            long result = 0;
            long.TryParse(Session.CreateQuery(hql).UniqueResult<long>().ToString(), out result);
            return result;
        }

        /// <summary>
        /// 跟据Hql返回单个对象
        /// </summary>
        /// <param name="hql"></param>
        /// <returns></returns>
        public object ExecHqlUniqueResult(string hql)
        {
            return Session.CreateQuery(hql).UniqueResult();
        }

        /// <summary>
        /// 跟据Sql返回单个对象
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public object ExecSqlUniqueResult(string sql)
        {
            return Session.CreateSQLQuery(sql).UniqueResult();
        }

        /// <summary>
        /// 执行hql语句，返回实体列表
        /// </summary>
        /// <param name="hql"></param>
        /// <returns></returns>
        public virtual IList<T> GetHqlList(string hql)
        {
            return Session.CreateQuery(hql).List<T>();
        }

        /// <summary>
        /// 跟据hql返回实体列表
        /// </summary>
        /// <param name="hql"></param>
        /// <param name="start"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        public virtual IList<T> GetHqlList(string hql, int start, int limit)
        {
            return Session.CreateQuery(hql).SetFirstResult(start).SetMaxResults(limit).List<T>();
        }

        /// <summary>
        /// 执行hql语句，返回实体列表
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public virtual IList<T> GetSqlList(string sql)
        {
            return Session.CreateSQLQuery(sql).AddEntity(typeof (T)).List<T>();
        }


        public IList<object[]> GetHqlObject(string hql)
        {
            return Session.CreateQuery(hql).List<object[]>();
        }

        public IList<object[]> GetSqlObject(string sql)
        {
            return Session.CreateSQLQuery(sql).List<object[]>();
        }

        public object[] ExecHql(string hql)
        {
            return Session.CreateQuery(hql).List<object[]>().FirstOrDefault();
        }

        public object[] ExecSql(string sql)
        {
            return Session.CreateSQLQuery(sql).List<object[]>().FirstOrDefault();
        }

        public IList<object[]> GetSqlObject(string sql, int start, int limit)
        {
            return Session.CreateSQLQuery(sql).SetFirstResult(start).SetMaxResults(limit).List<object[]>();
        }

        public void Add(IList<T> list)
        {
            // IList<object> strs;
            using (IStatelessSession session = base.SessionFactory.OpenStatelessSession())
            {
                var watch = new Stopwatch();
                watch.Start();
                using (ITransaction transaction = session.BeginTransaction())
                {
                    foreach (T item in list)
                    {
                        session.Insert(item);
                    }
                    transaction.Commit();
                }
                string str = watch.Elapsed.ToString();
                Console.WriteLine(str);
            }
        }

        public void AddWithBatchSize(IList<T> list)
        {


            Session.SetBatchSize(1000);
                foreach (var item in list)
                {
                    HibernateTemplate.Save(item);
                }

            


            foreach (T item in list)
            {
                HibernateTemplate.Save(item);
            }

        }


        public void ExecSql(IList<string> list)
        {

                 try{
                         
                      for (int i = 0; i < list.Count; i++)
                        {
                            IDbCommand cmd = Session.Connection.CreateCommand();
                            cmd.CommandText = list[i];
                            cmd.CommandType = CommandType.Text;
                            cmd.ExecuteNonQuery();
                        }
                 } catch{

                    for (int i = 0; i < list.Count; i++)
                    {
                        Session.CreateSQLQuery(list[i]);
                    }

                 }


        }

        public object ESql(string sql)
        {

            try
            {
                IDbCommand cmd = Session.Connection.CreateCommand();
                cmd.CommandText = sql;
                cmd.CommandType = CommandType.Text;
                return cmd.ExecuteScalar();
              
            }
            catch
            {
                return 0;
               

            }


        }

        #endregion
    }
}